package com.turing.data.engine;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.turing.data.vo.out.review.TaskElementVO.DrawResultVO;
import com.turing.common.util.StringUtils;

public class CombineLongText {

    private static int BIAS = 1000;

    public static List<String> doCombine(List<DrawResultVO> resultVOS, String rawText, String frontPattern, String endPattern) {

        String cut = fetchNearbyText(resultVOS.get(0), rawText);

        int begin = findPattern(cut, frontPattern, 0);
        int end = findPattern(cut, endPattern, 1);
        if (begin == -1) {
            begin = 0;
        }
        if (end == -1) {
            end = cut.length();
        } else {
            if (end < cut.length()) {
                end = end + 1;
            }

        }

//        List<Map<String, Integer>> oriPos = findNearByNumSeq(resultVOS.get(0).getText())
//        if (oriPos!=null && oriPos.size()>0){
//            oriPos.get(0).keySet().getAt(0)
//        }
        // (4) (1) (2) (3) (6)
        List<Map<String, Integer>> posMap = findNearByNumSeq(cut, "", 0);

        LinkedList<Integer> seq = new LinkedList<>();
        for (int i = 0; i < posMap.size(); i++) {
            Map<String, Integer> pos = posMap.get(i);
//            int seqText = pos.get(pos.keySet().iterator().next());
            int seqText = Integer.parseInt(pos.entrySet().iterator().next().getKey());
            seq.add(seqText);
        }
        int basePos = findBasePos(posMap, cut.length());
        List<String> result = new ArrayList<>();
        if (seq == null || seq.size() == 0) {
            result.add(StringUtils.isEmpty(resultVOS.get(0).getBusinessValue()) ? resultVOS.get(0).getText() : resultVOS.get(0).getBusinessValue());
            return result;
        }
        LinkedList<Integer> foundSeq = findSequence(seq, basePos);

        int first = foundSeq.get(0);
        int last = foundSeq.get(1);

        begin = posMap.get(first).entrySet().iterator().next().getValue() - 2;
        end = posMap.get(last).entrySet().iterator().next().getValue();

        end = findNextEndChar(end, '。', 1, cut);


//        begin = cut.substring(0, BIAS).lastIndexOf(first+"") == -1?BIAS:cut.substring(0, BIAS).lastIndexOf(first+"")
//        end = cut.substring(resultVOS.get(0).getText().size()+BIAS, cut.length()).indexOf(last + "") + (resultVOS.get(0).getText().size()+BIAS)

        String cut2 = cut.substring(begin, end);

        result.add(cut2);
        return result;
    }


    static int findNextEndChar(int end, char endC, int skip, String rawText) {
        int endCount = 0;
        for (int i = end; i < rawText.length(); i++) {
            char a = rawText.charAt(i);
            if (a == endC) {
                if (endCount < skip) {
                    endCount++;
                } else {
                    return i;
                }

            }
        }
        return end;
    }

    public static int findBasePos(List<Map<String, Integer>> posMap, int cutLength) {
        System.out.println(posMap);
        for (int i = 0; i < posMap.size(); i++) {
            Map<String, Integer> pos = posMap.get(i);

//            int seqText = pos.entrySet().iterator().next().getValue();
//            int seqPos = pos.get(seqText + "");
            int seqPos = pos.entrySet().iterator().next().getValue();
            if (seqPos >= BIAS && seqPos <= cutLength - BIAS) {
                return i;
            }
        }
        return 0;
    }

    public static String fetchNearbyText(DrawResultVO resultVO, String rawText) {
        String cut = rawText.substring(resultVO.getStart() - BIAS < 0 ? 0 : resultVO.getStart() - BIAS,
                resultVO.getEnd() + BIAS > rawText.length() ? rawText.length() : resultVO.getEnd() + BIAS);
        return cut;
    }

    public static String fetchNearbyText(DrawResultVO resultVO, String rawText, int bias) {
        if (bias == -1) {
            bias = BIAS;
        }
        String cut = rawText.substring(resultVO.getStart() - bias < 0 ? 0 : resultVO.getStart() - bias,
                resultVO.getEnd() + bias > rawText.length() ? rawText.length() : resultVO.getEnd() + bias);
        return cut;
    }

    /*
    检索文本附近的序号(1),(一),1.
    * */
    public static List<Map<String, Integer>> findNearByNumSeq(String oriText, String exText, int basePos) {

        List<Map<String, Integer>> results = new LinkedList<>();

        String regex = "[.\\n\\s\\S]*[(（]+[0123456789]+[)）]";

        String t = "";
//        for (int i = 0; i < (BIAS>oriText.length()?oriText.length():BIAS); i++) {
        for (int i = 0; i < oriText.length(); i++) {
            t = t + oriText.charAt(i);

            if (t.matches(regex)) {
                Map<String, Integer> posMap = new HashMap<>();

                int leftBracket = t.lastIndexOf('(');
                if (leftBracket == -1) {
                    leftBracket = t.lastIndexOf('（');
                }
//                if (i > BIAS && i<oriText.length()-BIAS){
//                    posMap.put(t.substring(leftBracket+1, t.length()-1), -1)
//                }else{
                posMap.put(t.substring(leftBracket + 1, t.length() - 1), i);
//                }

                t = "";
                results.add(posMap);
            }
        }

        return results;
    }


    public static void main(String[] args) {
//        String pattern = "(十一)"
//        println pattern.matches("[(（]+[0123456789一二三四五六七八九十]+[)）]")

        /*List<Map<String, Integer>> posMap = findNearByNumSeq(" 号《中国证监会关于证券投资基金估值业务的指导意见》及其他法律、法规的规定。本资产管理计划按照下述方法估值：（1）", "", 2);
//        List<Map<String, Integer>> posMap = findNearByNumSeq(cut, "", 0)

        System.out.println(posMap);

        LinkedList<Integer> seq = new LinkedList<>();
        for (int i = 0; i < posMap.size(); i++) {
            Map<String, Integer> pos = posMap.get(i);
            //seq.add(pos.keySet().getAt(0))
        }

        LinkedList<Integer> foundSeq = findSequence(seq, 3);
        System.out.println(foundSeq);*/
        String cut = "7. 具体投资品种估值方法（1）在交易所上市交易或挂牌转让的固定收益品种，采用中央国债登记结算公司提供的估值价确定公允价值。在估值技术难以可靠计量公允价值的情况下，按成本估值。（2）首次公开发行未上市的债券，采用估值技术确定公允价值，在估值技术难以可靠计量公允价值的情况下，按成本估值。（3）全国银行间债券市场交易的债券、资产支持证券等固定收益品种，采用中央国债登记结算公司提供的估值价确定公允价值。（4）同一债券同时在两个或两个以上市场交易的，按债券所处的市场分别估值。（5）证券投资基金的估值A、开放式基金（包括托管在场外的上市开放式基金 LOF）以估值日前一交易日基金净值估值，估值日前一交易日开放式基金份额净值未公布的，以此前最近一个交易日基金份额净值计算。79B、上市流通的证券投资基金按估值日其所在证券交易所的收盘价估值；估值日无交易的，以最近一个交易日的收盘价估值；C、货币基金以成本估值，每日按前一交易日的万份收益计提红利。（8）期货以估值日期期货交易所的当日结算价估值，估值当日无结算价的，且最近交易日后经济环境未发生重大变化的，采用最近交易日结算价估值。（9）如有确凿证据表明按上述方法进行估值不能客观反映其公允价值的，资产管理人可根据具体情况与资产托管人商定后，按最能反映公允价值的价格估值。如有新增事项，按国家最新规定估值。";
        List<Map<String, Integer>> posMap = findNearByNumSeq(cut, "", 0);

        LinkedList<Integer> seq = new LinkedList<>();
        for (int i = 0; i < posMap.size(); i++) {
            Map<String, Integer> pos = posMap.get(i);
//            int seqText = pos.get(pos.keySet().iterator().next());
            int seqText = Integer.parseInt(pos.entrySet().iterator().next().getKey());
            seq.add(seqText);
        }
        int basePos = findBasePos(posMap, cut.length());

        LinkedList<Integer> foundSeq = findSequence(seq, basePos);

        int first = foundSeq.get(0);
        int last = foundSeq.get(1);

        int begin = posMap.get(first).entrySet().iterator().next().getValue() - 2;
        int end = posMap.get(last).entrySet().iterator().next().getValue();

        end = findNextEndChar(end, '。', 1, cut);
        String cut2 = cut.substring(begin, end);
        System.out.println(posMap);
    }

    /*
    查找该文本具备的项模式
    oriText 待查找原文
    pattern 待查找模式
    type 0前查 1后查
    * */
    public static int findPattern(String oriText, String pattern, int type) {
        String t = "";
        if (type == 0) {
            for (int i = 0; i < oriText.length(); i++) {
                t = t + oriText.charAt(i);
                if (t.endsWith(pattern)) {
                    return i - pattern.length() + 1;
                }
            }
        }

        if (type == 1) {
            for (int i = 0; i < oriText.length(); i++) {
                t = t + oriText.charAt(i);
                if (t.endsWith(pattern)) {
                    return i - pattern.length() + pattern.length();
                }
            }
        }

        return -1;
    }

    public static LinkedList<Integer> findSequence(LinkedList<Integer> numSeq, int basePos) {
        int begin = basePos;
        int end = basePos;

        int pre = numSeq.get(basePos);
        System.out.println("base position is " + basePos + " " + numSeq.get(basePos) + "a" + pre);
        while (begin - 1 >= 0) {
            Integer i = numSeq.get(begin - 1);
            if (pre - 1 == i) {
                pre = i;
                begin--;
            } else {
                break;
            }
        }

        Integer front = numSeq.get(basePos);
        while (end + 1 < numSeq.size()) {
            Integer i = numSeq.get(end + 1);
            if (front + 1 == i) {
                front = i;
                end++;
            } else {
                break;
            }
        }

        System.out.println("final pos is " + begin + " " + end);
        LinkedList<Integer> foundSeq = new LinkedList<>();
//        for (int i = (begin < 0 ? 0 : begin); i <= end; i++) {
////            print(numSeq.get(i))
//            foundSeq.add(numSeq.get(i))
//        }

        foundSeq.add(begin);
        foundSeq.add(end);
        return foundSeq;
    }

    static List<String> combine(List<DrawResultVO> resultVOs) {

        List<String> result = new ArrayList<>();
        List<Page> pages = new ArrayList<>();
        for (DrawResultVO drawResultVO : resultVOs) {
            String businessValue = drawResultVO.getBusinessValue();
            List<String> position = drawResultVO.getPara_info();
            String[] positions = position.get(0).split("_");
            double degree = Double.parseDouble(drawResultVO.getDegree());
            int pageNum = Integer.parseInt(positions[1]);
            if (!StringUtils.isEmpty(businessValue)) {
                Page page = new Page(pageNum, businessValue, degree);
                pages.add(page);
            }
        }

        Map<Integer, List<Page>> map = Group.merge(pages);
        for (int key : map.keySet()) {
            StringBuilder newBusinessValue = new StringBuilder();
            for (Page pageVO : map.get(key)) {
                newBusinessValue.append(pageVO.businessValue);
            }
            result.add(newBusinessValue.toString());
        }

        return result;

    }

}
